var _ = require('lodash'),
    Q = require('q'),
    BarcodeEnum = require('../../../Barcode/server/controllers/Enum.server.controller'),
    QCEnum = require('../../../QC/server/controllers/Enum.server.controller'),
    userController = require('../../../User/server/controllers/users.server.controller'),
    terminalController = require('../../../CBO/server/controllers/Terminal.server.controller'),
    stationWorkController = require('../../../Initialize/server/controllers/StationWork.server.controller'),
    stationTerminalController = require('../../../Initialize/server/controllers/StationTerminal.server.controller'),
    barcodeMasterController = require('../../../Barcode/server/controllers/BarcodeMaster.server.controller'),
    operationController = require('../../../CBO/server/controllers/Operation.server.controller'),
    workLocationController = require('../../../CBO/server/controllers/WorkLocation.server.controller'),
    stationUserController = require('../../../Initialize/server/controllers/StationUser.server.controller'),
    bizRecordController = require('../../../Barcode/server/controllers/BizRecord.server.controller'),
    wareHouseController = require('../../../CBO/server/controllers/WareHouse.server.controller'),
    shiftController = require('../../../CBO/server/controllers/Shift.server.controller'),
    rcvRecordController = require('../../../ProduceWork/server/controllers/RcvRecord.server.controller'),
    Transaction = require('../../../Base/server/controllers/Transaction'),
    qcStandard = require('../../../QC/server/controllers/QCStandard.server.controller'),
    wareHouseController = require('../../../CBO/server/controllers/WareHouse.server.controller');

exports.processScan = function (req, res) {
    var parameter = req.body,
        barcode = parameter.Barcode,
        terminalUniqueID = parameter.TerminalUniqueID,
        flowSN = parameter.FlowSN,
        scanTime = parameter.ScanTime || Date.now(),
        qcResult = parameter.qcResult || null;//jiadx重平仪写入流水添加

    if (_.isString(scanTime)) {
        scanTime = scanTime.replace(/,/g, ' ');
    }

    queryBarcodeMaster(barcode).then(function (barcodeMasterRecord) {
        if (barcodeMasterRecord.BarcodeType === BarcodeEnum.BarcodeType.ItemMaster) {
            return doProcess(terminalUniqueID, barcodeMasterRecord, scanTime, qcResult);
        } else if (barcodeMasterRecord.BarcodeType === BarcodeEnum.BarcodeType.Person) {
            return doAttendance(terminalUniqueID, barcodeMasterRecord.EntityID, scanTime);
        } else {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '无法识别条码';
            newErr.message = '无法识别的条码，请重新扫描！';
            return Q.reject(newErr);
        }
    }).then(function () {
        var result = {
            status: 0
        };
        if (flowSN) {
            result.FlowSN = flowSN;
        }
        res.json(result);
    }).catch(function (err) {
        var result = {
            status: err.leval || 9
        };
        if (flowSN) {
            result.FlowSN = flowSN;
        }
        res.json(result);
    }).done();
};

exports.insertBizRecordST = function (req, res) {
    var parameter = req.body,
        barcode = parameter.Barcode,
        terminalUniqueID = parameter.TerminalUniqueID;

    var bizRecord = {
        BusinessStatus: parameter.BusinessStatus ? parameter.BusinessStatus : 0
    };
    queryHardwareInfo(terminalUniqueID).then(function (hardwareInfo) {
        _.merge(bizRecord, hardwareInfo);
        return queryOperation(barcode, bizRecord.Work);
    }).then(function (operation) {
        _.merge(bizRecord, operation);
        return queryUsers(bizRecord.WorkLocation, bizRecord.Terminal);
    }).then(function (users) {
        if (users) {
            _.merge(bizRecord, {Users: users});
        }
        return writeData(barcode, bizRecord);
    }).then(function (result) {
        res.json({
            Data: result,
            Error: null
        });
    }).catch(function (err) {
        res.json({
            Data: null,
            Error: err
        });
    })
        .done();
};

exports.updateBizRecordST = function (req, res) {
    var parameter = req.body,
        barcode = parameter.Barcode;

    barcodeMasterController.findBarcodeMaster(barcode, function (err, record) {
        if (err) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询物料错误';
            newErr.message = '无法识别的条码，请重新扫描！';
            res.json({
                Data: null,
                Error: newErr
            });
            return;
        }
        bizRecordController.updateOneST(record._id, function (err, result) {
            if (err) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '更新流水错误';
                newErr.message = '更新条码流水错误！';
                res.json({
                    Data: null,
                    Error: newErr
                });
                return;
            }
            res.json({
                Data: result,
                Error: null
            });
        });
    });
};

function doAttendance(terminalUniqueId, userId, scanTime) {
    var deferred = Q.defer();

    var workLocation, terminal;
    checkUserValid(userId).then(function () {
        return queryHardwareInfo(terminalUniqueId);
    }).then(function (hardwareInfo) {
        workLocation = hardwareInfo.WorkLocation;
        terminal = hardwareInfo.Terminal;
        return stationUserController.insert({
            WorkLocation: workLocation,
            User: userId,
            Terminal: terminal,
            StartDateTime: scanTime
        });
    }).then(function (record) {
        deferred.resolve();
    }).catch(function (err) {
        deferred.reject(err);
    })
        .done();


    return deferred.promise;
}

function doProcess(terminalUniqueId, barcodeMaster, scanTime, qcResult) {
    var deferred = Q.defer();

    var bizRecord = {
        BarcodeMaster: barcodeMaster._id,
        CollectDateTime: scanTime

    }, operation, workLocationShared;

    if (qcResult) {
        _.merge(bizRecord, {
            QCType: 0,
            QCStatus: 0
        });
    }

    var insertBizRecord, itemMasterId, nowWork;

    queryHardwareInfo(terminalUniqueId).then(function (hardwareInfo) {
        workLocationShared = hardwareInfo.WorkLocationShared;
        delete hardwareInfo.WorkLocationShared;
        _.merge(bizRecord, hardwareInfo);
        if (barcodeMaster.ItemMaster) {
            itemMasterId = barcodeMaster.ItemMaster._id;//jiadx重平仪
            nowWork = bizRecord.Work; //jiadx重平仪
            return queryOperation(barcodeMaster.ItemMaster._id, bizRecord.Work);
        } else {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '数据错误';
            newErr.message = '条码主档没有物料信息';
            return Q.reject(newErr);
        }
    }).then(function (record) {
        operation = record;
        _.merge(bizRecord, {
            Operation: record._id,
            OperationName: record.Name
        });
        var bindContext = { User: barcodeMaster.Users ? barcodeMaster.Users[0] : null };
        _.merge(bindContext, {
            WorkLocation: bizRecord.WorkLocation,
            WorkLocationName: bizRecord.WorkLocationName,
            Work: bizRecord.Work,
            WorkName: bizRecord.WorkName
        });
        return barcodeMasterController.streamValidationReader(barcodeMaster, record, bindContext);
    }).then(function () {
        if (workLocationShared) {
            return findLastAttendanceUser(bizRecord.WorkLocation);
        } else {
            return findAttendanceUsers(bizRecord.WorkLocation, scanTime);
        }
    }).then(function (users) {
        if (users.length > 0) {
            _.merge(bizRecord, { Users: users });
        }
        return queryBusinessStatus(bizRecord.WorkLocation, bizRecord.Terminal, barcodeMaster._id);
    }).then(function (businessStatus) {
        bizRecord.BusinessStatus = businessStatus;
        return writeData(barcodeMaster.Barcode, bizRecord);
    }).then(function (insertResult) {
        insertBizRecord = insertResult.BizRecord;
        return addStockQty(barcodeMaster, bizRecord, operation, scanTime);
    }).then(function () {
        //jiadx重平仪写入质检记录
        return operateQCRecord(insertBizRecord, itemMasterId, nowWork, qcResult);
    }).then(function () {
        deferred.resolve();
    }).catch(function (err) {
        deferred.reject(err);
    }).done();

    return deferred.promise;
}

function queryHardwareInfo(terminalUniqueID) {
    var deferred = Q.defer();

    terminalController.findByUniqueID(terminalUniqueID, function (err, terminalRecord) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (terminalRecord == null) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询终端错误';
            newErr.message = '请检查查询参数！';
            deferred.reject(newErr);
            return;
        }
        var hardwareInfo = {
            Terminal: terminalRecord._id,
            TerminalName: terminalRecord.Name
        };
        stationWorkController.getStationWorksByTerminalID(terminalRecord._id, function (err, stationWorkRecords) {
            if (err) {
                deferred.reject(err);
                return;
            }
            if (stationWorkRecords.length > 0) {
                hardwareInfo.WorkLocation = stationWorkRecords[0].WorkLocation._id;
                hardwareInfo.WorkLocationName = stationWorkRecords[0].WorkLocation.Name;
                hardwareInfo.WorkLocationShared = stationWorkRecords[0].WorkLocation.IsShared;
                hardwareInfo.Work = stationWorkRecords[0].Work._id;
                hardwareInfo.WorkName = stationWorkRecords[0].Work.Name;
            }
            deferred.resolve(hardwareInfo);
        });
    });

    return deferred.promise;
}

function queryOperation(itemMaster, work) {
    var deferred = Q.defer();

    operationController.findByItemMasterAndWork(itemMaster, work, function (err, result) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!result) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '非法数据';
            newErr.message = '没有找到对应的工序';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(result);
    });

    return deferred.promise;
}

function queryUsers(workLocationId, terminalId) {
    var deferred = Q.defer();

    stationUserController.findByWorkLocationAndTerminal(workLocationId, terminalId, function (err, record) {
        if (err) {
            deferred.reject(err);
            return;
        }
        deferred.resolve(record);
    });

    return deferred.promise;
}

function writeData(barcode, bizRecord) {
    var deferred = Q.defer();
    
    bizRecordController.insert(bizRecord, function (err, record) {
        if (err) {
            deferred.reject(err);
            return;
        }
        delete bizRecord.BarcodeMaster;
        delete bizRecord.CollectDateTime;
        bizRecord.BizRecord = record._id;
        barcodeMasterController.updateByValue(barcode, bizRecord, function (err, result) {
            if (err) {
                deferred.reject(err);
                return;
            }
            result.BizRecord = record;//重平仪写入质检记录需要流水信息,此处添加
            deferred.resolve(result);
        });
    });

    return deferred.promise;
}

function queryBarcodeMaster(barcode) {
    var deferred = Q.defer();

    barcodeMasterController.findBarcodeMaster(barcode, function (err, barcodeMasterRecord) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (barcodeMasterRecord == null) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '条码扫描失败';
            newErr.message = '该条码没有对应的条码主档！';
            deferred.resolve(newErr);
        }
        deferred.resolve(barcodeMasterRecord);
    });

    return deferred.promise;
}

function checkUserValid(userId) {
    var deferred = Q.defer();

    userController.getUserByID(userId, function (err, user) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (user === null) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询用户错误';
            newErr.message = '没有找到对应的用户';
            deferred.reject(newErr);
            return;
        }
        if (user.IsEffective) {
            deferred.resolve();
        } else {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '用户失效';
            newErr.message = '该用户已失效';
            deferred.reject(newErr);
        }
    });

    return deferred.promise;
}

function queryBusinessStatus(workLocationId, terminalId, barcodeMasterId) {
    var deferred = Q.defer();

    stationTerminalController.findBusinessStatus(workLocationId, terminalId).then(function (businessStatus) {
        if (businessStatus === 2) {
            bizRecordController.findNearestRecord(workLocationId).then(function (records) {
                if (records.length === 1 && records[0].BarcodeMaster === barcodeMasterId) {
                    deferred.resolve(1);
                } else {
                    deferred.resolve(0);
                }
            }, function (err) {
                deferred.reject(err);
            });
        } else {
            deferred.resolve(businessStatus || 0);
        }
    }, function (err) {
        deferred.reject(err);
    });

    return deferred.promise;
}

function addStockQty(barcodeMaster, bizRecord, operation, scanTime) {
    var deferred = Q.defer();

    if (operation && operation.IsStoragePoint) {
        workLocationController.findById(
            bizRecord.WorkLocation, { Department: 1 }, { path: 'Department', select: 'Name' }
        ).then(function (workLocationRecord) {
            if (!workLocationRecord) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询工位错误';
                newErr.message = '没有找到对应工位';
                deferred.reject(newErr);
                return;
            }
            return wareHouseController.findByDepartmentDeep(workLocationRecord.Department._id);
        }).then(function (wareHouse) {
            if (!wareHouse) {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询仓库';
                newErr.message = '没有找到对应的仓库';
                return Q.reject(newErr);
            }
            return rcvRecordController.addStockQty([{
                BarcodeMaster: barcodeMaster._id,
                Barcode: barcodeMaster.Barcode,
                ItemMaster: barcodeMaster.ItemMaster ? barcodeMaster.ItemMaster._id : '',
                DescSeg1: barcodeMaster.DescSeg1,
                DescSeg2: barcodeMaster.DescSeg2,
                BusinessDocID: barcodeMaster.MO ? barcodeMaster.MO._id : '',
                RcvUser: (bizRecord.Users && bizRecord.Users.length > 0) ? bizRecord.Users[0] : null,
                RcvOperation: operation._id,
                BizRecord: bizRecord.BizRecord,
                WareHouse: wareHouse._id,
                RcvDateTime: scanTime
            }]);
        }).then(function () {
            deferred.resolve();
        }, function () {
            deferred.resolve();
        });
    } else {
        deferred.resolve();
    }

    return deferred.promise;
}

//写入质检记录
function operateQCRecord(insertBizRecord, itemMasterId, nowWork, qcResult) {
    var deferred = Q.defer();
    if (qcResult && qcResult.length > 0) {//如果质检结果存在,则判定为重平仪写入质检记录
        var codes = [], codeValue = {};
        _.forEach(qcResult, function (qc) {
            codes.push(qc.Code);
            codeValue[qc.Code] = qc.NormValue;
        });
        qcStandard.findQCStandardByCondition(itemMasterId, nowWork, function (qcStandards) {
            var qcRecords = [];
            _.forEach(qcStandards, function (qcStandard) {
                if (codes.indexOf(qcStandard.QCNorm.Code) > 0) {
                    var isType = 0;
                    if (Number(codeValue[qcStandard.QCNorm.Code]) > qcStandard.ValueUpperLimit ||
                        Number(codeValue[qcStandard.QCNorm.Code]) < qcStandard.ValueLowerLimit) {
                        isType = 1;
                    } else {
                        isType = 0;
                    }
                    qcRecords.push({
                        BizRecord: insertBizRecord._id,
                        QCNorm: qcStandard.QCNorm._id,
                        NormValue: Number(codeValue[qcStandard.QCNorm.Code]),
                        IsQualified: isType
                    });
                }
            });
            Transaction.BatchSaveByTran([
                    {EntityName: 'QCRecord', Records: qcRecords}
                ],
                function (err, result) {
                    if (err) {
                        deferred.reject(err);
                        return;
                    }
                    deferred.resolve(result);
                }
            );
        });
    } else {
        deferred.resolve();
    }
    return deferred.promise;
}

function findLastAttendanceUser (workLocation) {
    var deferred = Q.defer();

    stationUserController.findLastAttendance(workLocation, 'User').then(function (record) {
        if (record) {
            deferred.resolve([record.User]);
        } else {
            deferred.resolve([]);
        }
    }, function (err) {
        deferred.reject(err);
    });

    return deferred.promise;
}

function findAttendanceUsers (workLocation, scanTime) {
    var deferred = Q.defer();

    shiftController.findShift(scanTime).then(function (record) {
        if (record) {
            return stationUserController.findDurationAttendance(workLocation, record.StartTime, record.EndTime);
        } else {
            return Q.resolve([]);
        }
    }).then(function (users) {
        deferred.resolve(users);
    }).catch(function (err) {
        deferred.reject(err);
    })
    .done();

    return deferred.promise;
}